package com.qtenv.datasync.api.degao;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.setting.Setting;
import com.qtenv.datasync.constant.AppConstants;
import com.qtenv.datasync.service.entity.convert.DataMeterH;
import com.qtenv.datasync.service.entity.convert.FileFlowMeter;
import com.qtenv.datasync.service.entity.degao.DgTerminalArchive;
import com.qtenv.datasync.service.entity.degao.DgTerminalHistory;
import com.qtenv.datasync.service.entity.msmapper.DgTerminalFileFlowMapper;
import com.qtenv.datasync.service.entity.msmapper.DgTerminalHistoryHMapper;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @ClassName DeGaoApi
 * @Author tanyongle, CBL
 * @Date 2020/4/14 14:16, 2020年4月15日
 **/
public class DeGaoApi {
    private static final String TYPE_ALL = "all";

    /**
     * 对接地址与端口
     */
    private static final String WEB_API = "http://121.40.63.15:7889/WebApi/";
    //    private static final String WEB_API = "http://121.40.63.15:8869/WebApi/";
//    private static final String WEB_API = "http://121.40.63.15:8887/WebApi/";
    private static final String API_GetScadaList = WEB_API + "GetScadaList?";
    private static final String API_GetScadaListForRealTime = WEB_API + "GetScadaListForRealTime?";
    private static final String API_GetAllScadaListForRealTime = WEB_API + "GetAllScadaListForRealTime?";
    private static final String API_GetScadaValueByUserTerminals = WEB_API + "getScadaValueByUserTerminals?";
    private static final String API_GetScadaValueByUserTerminalsForID = WEB_API + "GetScadaValueByUserTerminalsForID?";
    public static final String TIME_BEGIN_SURFIX = "T00:00:00";
    public static final String TIME_END_SURFIX = "T23:59:59";

    private static final String JC_API = "http://watermonitor.swdegao.com:7888/ruoyi-webApiServerPush/api/";
    private static final String JC_API_GetTerminalDblist = JC_API + "getTerminalDblist?";
    private static final String JC_API_GetTerminalDbHistory = JC_API + "getTerminalDbHistory?";

    /**
     * @param pageNum   页码，默认1
     * @param pageSize  每页数量，默认20
     * @param sheetsCode  区域编号
     * @return [{
     *    "createBy": null, "updateBy": null, "updateTime": null, "id": 138705, "tid": 249, "tenantId": "810729", "terminalName": "插入式2",
     *    "terminalId": "240112141", "terminalTime": null, "totalFlow": -87.89, "readNumber": 77.80, "reverseNumber": 165.68, "instantNumber": null,
     *    "instantVelocity": null, "pressure": 0.00, "terminalVol": 7.34, "terminalCsq": 208, "valveState": null, "locationNb": "1895384594908184576",
     *    "terminalCsqDescribe": null, "readDate": "2024-09-01 05:55:00", "createTime": "2025-03-07T17:04:50.000+08:00", "loginUserId": null, "systemFlag": null,
     *    "sheetsCode": null, "signPlatform": 3, "imei": "862821066007325", "valveStatus": null, "userId": "1714302817"
     * }]
     */
    public static String getTerminalDblist(Integer pageNum, Integer pageSize,String sheetsCode) {
        String params = "pageNum=" + pageNum + "&pageSize=" + pageSize + "&sheetsCode=" + sheetsCode;
        return HttpUtil.get(JC_API_GetTerminalDblist + params);
    }

    /**
     * @param pageNum   页码，默认1
     * @param pageSize  每页数量，默认20
     * @param locationNb  设备编号
     * @param startTime  开始时间
     * @param endTime  结束时间
     * @return [{
     *             "id": 3029474,
     *             "tenantId": "810727",
     *             "terminalName": null,
     *             "terminalId": "221015718",
     *             "totalFlow": 0.00,
     *             "readNumber": 0.00,
     *             "reverseNumber": 0.00,
     *             "instantNumber": 0.00,
     *             "pressure": 0.00,
     *             "terminalVol": 7.37,
     *             "terminalCsq": 10,
     *             "readDate": "2025-02-24 00:00:00",
     *             "locationNb": "1892138118371344384",
     *             "instantVelocity": null,
     *             "terminalCsqDescribe": null,
     *             "valveState": null,
     *             "createTime": "2025-02-27 09:51:22"
     *         }]
     */
    public static String getTerminalDbHistory(Integer pageNum, Integer pageSize,String locationNb,String startTime,String endTime) {
        String params = "pageNum=" + pageNum + "&pageSize=" + pageSize + "&locationNb=" + locationNb + "&startTime=" + startTime + "&endTime=" + endTime;
        return HttpUtil.get(JC_API_GetTerminalDbHistory + params);
    }


    /**
     * @param type   类型
     * @param AreaID 分区ID
     * @return [{
     * "Id": 211,
     * "Name": "太阳能RTU001",
     * "ModelName": "插入式电磁流量计300",
     * "Address": null,
     * "Pipe": null,
     * "PipeDN": 0,
     * "Period": 0,
     * "Status": "使用",
     * "NameFactory": null,
     * "DateBuild": null
     * }]
     */
    public static String GetScadaList(String type, int AreaID) {
        String params = "Type=" + type + "&AreaID=" + AreaID;
        return HttpUtil.get(API_GetScadaList + params);
    }

    /**
     * @param type   类型
     * @param AreaID 区域ID
     * @return [{
     * "Id": 217,
     * "UserTerminals": 204,
     * "Name": "太阳能RTU004",
     * "ModelName": "机械大表",
     * "Address": null,
     * "Pipe": null,
     * "PipeDN": 0,
     * "Period": 0,
     * "Status": "在档",
     * "NameFactory": null,
     * "DateBuild": null,
     * "CurrentTotalFlow": null,
     * "CurrentReadNumber": null,
     * "CurrentReverseNumber": null,
     * "CurrentPressure": null,
     * "CurrentElectromagneticPressure": null,
     * "CurrentTerminalVol": null,
     * "CurrentTerminalCSQ": null,
     * "CurrentReadDate": null
     * }]
     */
    public static String GetScadaListForRealTime(String type, int AreaID) {
        String params = "Type=" + type + "&AreaID=" + AreaID;
        return HttpUtil.get(API_GetScadaListForRealTime + params);
    }

    /**
     * 获取区域设备Scada的档案数据及最新设备数据
     *
     * @param type     类型：[all,...]
     * @param areaCode 区域代号
     * @return ""
     * @date 2019年12月3日, 2020年4月15日
     * @author tyl, CBL
     */
    public static String GetAllScadaListForRealTime(String type, String areaCode) {
        String params = "type=" + type + "&areacode=" + areaCode;
        return HttpUtil.get(API_GetAllScadaListForRealTime + params);
    }

    /**
     * 获取设备Scada数据历史数据
     *
     * @param tids      设备terminal_id 以逗号隔开
     * @param timeBegin 开始时间
     * @param timeEnd   结束时间
     * @return [
     * {
     * "Id": 106,
     * "Name": "RTU600",
     * "Type": null,
     * "Address": null,
     * "Data": [GetScadaValue
     * {
     * "Time": "2018-04-10 00:00:00",
     * "Value": {
     * "TotalFlow": 160890,
     * "ReadNumber": 161589,
     * "ReverseNumber": 699,
     * "Pressure": 0
     * }
     * }
     * ]
     * }
     * ]
     * @date 2019年12月3日, 2020年4月15日
     * @author tyl, CBL
     */
    public static String GetScadaValueByUserTerminals(String tids, String timeBegin, String timeEnd) {
        String params = "Ids=" + tids + "&TimeBeg=" + timeBegin + "&TimeEnd=" + timeEnd;
        return HttpUtil.get(API_GetScadaValueByUserTerminals + params);
    }

    /**
     * @param tids
     * @param dataId
     * @return
     */
    public static String GetScadaValueByUserTerminalsForID(String tids, String dataId) {
        String params = "ids=" + tids + "&dataID=" + dataId;
        //System.out.println(API_GetScadaValueByUserTerminalsForID + params);
        return HttpUtil.get(API_GetScadaValueByUserTerminalsForID + params);
    }

    /**
     * @param object
     * @param fieldName
     * @param value
     * @date 2020年4月15日
     * @author CBL
     */
    private static void SetObjectFieldValue(Object object, String fieldName, Object value) {
        try {
            Class c = object.getClass();
            Field f = c.getDeclaredField(fieldName);
            f.setAccessible(true);
//            System.out.println(f.getGenericType().toString() + " ===== fileName=" + fieldName + " ===== value=" + value);
            if (f.getGenericType().toString().equals("class java.lang.Integer")) {
                f.set(object, value == null ? null : Integer.valueOf(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.lang.Float")) {
                f.set(object, value == null ? null : Float.valueOf(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.lang.Double")) {
                f.set(object, value == null ? null : Double.valueOf(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.lang.Long")) {
                f.set(object, value == null ? null : Long.valueOf(value.toString()));
            } else if (f.getGenericType().toString().equals("java.lang.Boolean")) {
                f.set(object, value == null ? null : Boolean.getBoolean(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.lang.String")) {
                f.set(object, value == null ? null : value.toString());
            } else if (f.getGenericType().toString().equals("class java.math.BigDecimal")) {
                f.set(object, value == null ? null : new BigDecimal(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.sql.Date")) {
                java.util.Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value.toString());
                f.set(object, value == null ? null : new java.sql.Date(date.getTime()));
            } else if (f.getGenericType().toString().equals("class java.handler.Date")) {
                f.set(object, value == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value.toString()));
            } else if (f.getGenericType().toString().equals("class java.sql.Timestamp")) {
                f.set(object, value == null ? null : new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value.toString()).getTime()));
            } else {
                f.set(object, value);
            }
        } catch (Exception e) {
        }
    }

    private static List<String> GetTimeRanges(String strDateBegin, String strDateEnd, Integer daySpan) {
        List<String> timeRanges = new ArrayList<>();
        LocalDate dateBegin = LocalDate.parse(strDateBegin);
        LocalDate dateEnd = LocalDate.parse(strDateEnd);
        int dSpan = (int) (dateEnd.toEpochDay() - dateBegin.toEpochDay());
        if (dSpan < daySpan || dSpan == daySpan) {
            timeRanges.add(strDateBegin + TIME_BEGIN_SURFIX + "~" + strDateEnd + TIME_END_SURFIX);
        } else {
            boolean flag = true;
            while (flag) {
                String timeRange = dateBegin.toString() + TIME_BEGIN_SURFIX + "~";
                LocalDate tmpDate = dateBegin.plusDays(daySpan - 1);
                if (tmpDate.isBefore(dateEnd)) {
                    timeRange += (tmpDate.toString() + TIME_END_SURFIX);
                    dateBegin = tmpDate.plusDays(1);
                } else {
                    timeRange += (dateEnd.toString() + TIME_END_SURFIX);
                    flag = false;
                }
                timeRanges.add(timeRange);
            }
        }

        return timeRanges;
    }

    /**
     * 根据目标类型和配置文件获取档案
     *
     * @param clazz        目标类型
     * @param propFileName 配置文件名（xxx.properties），放在resources目录下
     * @param <E>
     * @return
     * @date 2020年4月15日
     * @author CBL
     */
    public static <E> List<E> GetMeterFiles(Class<E> clazz, String propFileName, String fetchBy, String areaSymbol) {
        Setting setting = new Setting(propFileName);
        List<E> result = new ArrayList<>();
        String[] areaSymbols = areaSymbol.split(",");
        for (String symbol : areaSymbols) {
            String scadaList = (fetchBy.equals("AreaID") ? GetScadaListForRealTime(TYPE_ALL, Integer.valueOf(symbol)) : GetAllScadaListForRealTime(TYPE_ALL, symbol));
            JSONArray meterArray = JSONUtil.parseArray(scadaList);
            for (int i = 0; i < meterArray.size(); i++) {
                JSONObject object = meterArray.getJSONObject(i);
//                System.out.println(JSONUtil.toJsonPrettyStr(object));
                try {
                    E instance = clazz.newInstance();
                    for (String key : setting.keySet()) {
                        SetObjectFieldValue(instance, setting.getStr(key), object.get(key));
                    }
                    result.add(instance);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return result;
    }

    public static <E> List<E> GetMeterFilesByAreaId(Class<E> clazz, String propFileName, String areaID) {
        return GetMeterFiles(clazz, propFileName, "AreaID", areaID);
    }

    public static <E> List<E> GetMeterFilesByAreaCode(Class<E> clazz, String propFileName, String areaCode) {
        return GetMeterFiles(clazz, propFileName, "AreaCode", areaCode);
    }

    public static <E> List<E> GetMeterDatas(Class<E> clazz, String propFileName, String tids, String timeBegin, String timeEnd) {
        return GetMeterDatas(clazz, propFileName, tids, timeBegin, timeEnd, 15);
    }

    /**
     * 根据目标类型、配置文件、终端ID获取数据
     *
     * @param clazz        目标类型
     * @param propFileName 配置文件名（xxx.properties），放在resources目录下
     * @param tids         终端ID，逗号（英文逗号）隔开，为null时需在配置文件配置terminalIds参数
     * @param strDateBegin
     * @param strDateEnd
     * @param daySpan
     * @return
     * @date 2020年4月15日
     * @author CBL
     */
    public static <E> List<E> GetMeterDatas(Class<E> clazz, String propFileName, String tids, String strDateBegin, String strDateEnd, Integer daySpan) {
        Setting setting = new Setting(propFileName);

        List<String> timeRanges = GetTimeRanges(strDateBegin, strDateEnd, daySpan);
        List<E> result = new ArrayList<>();
        for (String timeRange : timeRanges) {
            String[] timeArr = timeRange.split("~");
            String dataList = GetScadaValueByUserTerminals(tids, timeArr[0], timeArr[1]);
            JSONArray objectArray = JSONUtil.parseArray(dataList);
            // System.out.println(JSONObject.toJSONString(objectArray, true));
            for (int i = 0; i < objectArray.size(); i++) {
                JSONObject object = objectArray.getJSONObject(i);
                String terminalId = object.getStr("Id");
                JSONArray dataArray = object.getJSONArray("Data");
                for (int j = 0; j < dataArray.size(); j++) {
                    Object timeObj = dataArray.getJSONObject(j).get("Time");
                    JSONObject valueObj = dataArray.getJSONObject(j).getJSONObject("Value");
                    try {
                        E instance = clazz.newInstance();
                        for (String key : setting.keySet()) {
                            SetObjectFieldValue(instance, setting.getStr(key), valueObj.get(key));
                        }
                        // 设置TerminalId
                        SetObjectFieldValue(instance, setting.getStr("Id"), terminalId);
                        // 设置Time
                        SetObjectFieldValue(instance, setting.getStr("Time"), timeObj);
                        result.add(instance);
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return result;
    }


    public static void main(String[] args) {
        String result;

//        result = DeGaoApi.GetScadaList(TYPE_ALL, 150);
//        System.out.println(result);

//        result = GetScadaListForRealTime(TYPE_ALL, 150);
//        System.out.println(result);

        // =================================拉取大表档案=================================
        // 福州闽侯
//        result = DeGaoApi.GetAllScadaListForRealTime(TYPE_ALL, "001005003002");
        // 肇庆怀集
//        result = DeGaoApi.GetAllScadaListForRealTime(TYPE_ALL, "001022004001002");
        result = DeGaoApi.GetAllScadaListForRealTime(TYPE_ALL, "001002013001"); // 测试区域
        System.out.println(result);
//        JSONArray jsonArray = JSONUtil.parseArray(result);
//        jsonArray.forEach(json -> {
//            JSONObject jbj = JSONUtil.parseObj(json);
//            DgTerminalArchive dgTerminalArchive = jbj.toBean(DgTerminalArchive.class);
//            FileFlowMeter fileFlowMeter = DgTerminalFileFlowMapper.INSTANCE.toFileFlowMeter(dgTerminalArchive);
//            if (fileFlowMeter.getCREATE_DATE() == null) {
//                fileFlowMeter.setCREATE_DATE(new Date());
//            }
//            System.out.println(JSONUtil.toJsonPrettyStr(fileFlowMeter));
//            Entity entity = Entity.parse(fileFlowMeter);
//            entity.setTableName("tbl_file_flow_meter");
//            entity.set("tenant_id", AppConstants.APP_TENANT_ID);
//            try {
//                List<FileFlowMeter> fileFlowMeterList = Db.use().query("select * from dywdma.tbl_file_flow_meter where tenant_id=?", FileFlowMeter.class, AppConstants.APP_TENANT_ID);
//                if (CollUtil.isNotEmpty(fileFlowMeterList)) {
//                    long count = fileFlowMeterList.stream().filter(item -> item.getFFM_ID().contains(entity.getStr("FFM_ID"))).count();
//                    if (count == 0) {
//                        Db.use().insert(entity);
//                    }
//                } else {
//                    Db.use().insert(entity);
//                }
//            } catch (SQLException e) {
//                throw new RuntimeException(e);
//            }
//        });
        // =================================拉取大表档案=================================

        // =================================拉取大表历史数据=================================
//        String startTimePrefix = "T00:00:00";
//        String endTimePrefix = "T23:59:59";
//        String startDateStr = "2023-11-30";
//        String endDateStr = "2023-11-30";
//        LocalDate startDate = LocalDate.parse(startDateStr);
//        LocalDate endDate = LocalDate.parse(endDateStr);
//        try {
//            List<FileFlowMeter> terminalList = Db.use().query("select * from dywdma.tbl_file_flow_meter where tenant_id=? and YL='1'", FileFlowMeter.class, AppConstants.APP_TENANT_ID);
//            String tids = String.join(",", terminalList.stream().map(item -> item.getFFM_ID().substring(6)).collect(Collectors.toList()));
//            System.out.println("tids===" + tids);

//            while (startDate.isBefore(endDate) || startDate.equals(endDate)) {
//                result = DeGaoApi.GetScadaValueByUserTerminals("7611", startDate + startTimePrefix, startDate + endTimePrefix);
//                System.out.println(result);
//                JSONArray jsonArray = JSONUtil.parseArray(result);
//                jsonArray.forEach(json -> {
//                    List<Entity> entityList = CollUtil.newArrayList();
//                    String userTerminals = JSONUtil.parseObj(json).getStr("Id");
//                    JSONArray dataArray = JSONUtil.parseObj(json).getJSONArray("Data");
//                    dataArray.forEach(da -> {
//                        JSONObject daObj = JSONUtil.parseObj(da);
//                        DgTerminalHistory dgTerminalHistory = daObj.getJSONObject("Value").toBean(DgTerminalHistory.class);
//                        dgTerminalHistory.setUserTerminals(userTerminals);
//                        dgTerminalHistory.setReadDate(DateUtil.parse(daObj.getStr("Time"), DatePattern.NORM_DATETIME_FORMAT).toJdkDate());
//
//                        DataMeterH dataMeterH = DgTerminalHistoryHMapper.INSTANCE.toDataMeterH(dgTerminalHistory);
//                        Entity entity = Entity.parse(dataMeterH);
//                        entity.setTableName("tbl_data_meter_h_ods");
//                        entityList.add(entity);
//                    });
//
//                    System.out.println(JSONUtil.toJsonPrettyStr(entityList));
//                    try {
//                        Db.use().insert(entityList);
//                    } catch (SQLException e) {
//                        throw new RuntimeException(e);
//                    }
//                });
//                startDate = startDate.plusDays(1);
//            }
//        } catch (SQLException e) {
//            throw new RuntimeException(e);
//        }
        // =================================拉取大表历史数据=================================
//
//        result = DeGaoApi.GetScadaValueByUserTerminalsForID("790,791", "552105343");
//        result = DeGaoApi.GetScadaValueByUserTerminalsForID("790", "552515343");
//        System.out.println(result);

//        JSONArray meterArray = JSONUtil.parseArray(result);
//        System.out.println(meterArray.size());
//        for (int i = 0; i < meterArray.size(); i++) {
//            JSONObject object = meterArray.getJSONObject(i);
//            System.out.println(JSONUtil.toJsonPrettyStr(object));
//            {
//                "Address":"345",
//                "Lng":"113.4755937",
//                "UserTerminals":352,
//                "UserCode":"N00000036",
//                "Imei":"865933032453363",
//                "Name":"怀集高铁站宿舍下",
//                "CurrentTotalFlow":111748.2,
//                "CurrentTerminalVol":6.9,
//                "TerminalFactoryID":"DG-1800341",
//                "TerminalPhone":"1064708228088",
//                "PlatformId":0,
//                "CurrentTerminalCSQ":98,
//                "Status":"使用",
//                "CurrentElectromagneticPressure":99,
//                "ModelName":"管段式-电磁水表-150-电池供电-ONENET",
//                "UserName":"怀集县自来水公司",
//                "AgreementId":1,
//                "PipeDN":0,
//                "Period":0,
//                "CurrentPressure":0.17,
//                "CurrentReadDate":"2019-12-13 15:45:00",
//                "Id":454,
//                "CurrentReverseNumber":468.46,
//                "CurrentReadNumber":112216.66,
//                "Lat":"22.9527075"
//            }
    }

//        String fileName1 = "static/vendor/NTDeGao/DeGaoMeterFile.json";
//        List<MeterFileEntity> meterFileEntityList1 = GetMeterFilesByAreaId(MeterFileEntity.class, fileName1, "150");
//        System.out.println(JSONObject.toJSONString(meterFileEntityList1, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat));
//        List<MeterFileEntity> meterFileEntityList2 = GetMeterFilesByAreaCode(MeterFileEntity.class, fileName1, "001002008");
//        System.out.println(JSONObject.toJSONString(meterFileEntityList2, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat));

//        String fileName2 = "DeGaoMeterData.setting";
//        String tids = "790";
//        String strDateBegin = "2021-12-27";
//        String strDateEnd = "2021-12-27";
//
//        List<MeterDataHisEntity> datas = DeGaoApi.GetMeterDatas(MeterDataHisEntity.class, fileName2, tids, strDateBegin, strDateEnd);
//        System.out.println(JSONObject.toJSONString(dataEntityList, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat));
//        System.out.println("数量=" + datas.size());
//        for (MeterDataEntity data : datas) {
//            System.out.println(JSONObject.toJSONString(data, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat));
//        }

//        String fileName = "static/vendor/NTDeGao/DeGaoMeterFile.json";
//        List<DeviceModel> modelList = DeGaoApi.GetMeterFilesByAreaCode(DeviceModel.class, fileName, "001002007");
//        List<DeviceModel> modelList = DeGaoApi.GetMeterFilesByAreaId(DeviceModel.class, fileName, "149");
//        System.out.println(modelList);

//        System.out.println(JSONUtil.toJsonPrettyStr(GetAllScadaListForRealTime(TYPE_ALL, "001002010")));
//    }
}
